/**
 * 基础形状演员类
 */

import * as THREE from "./three.js/build/three.module.js";

import { CapsuleGeometry } from "./A3Geometrys.js";
import A3Actor from "./A3Actor.js";
import { getMeshShape, isNull } from "./A3Common.js";

const BasicShapeTypes = {
  Box:"Box",
  Capsule:"Capsule",
  Cone:"Cone",
  Cylinder:"Cylinder",
  Sphere:"Sphere",
  Torus:"Torus",
  Plane:"Plane",
}

// 生成基础图形Mesh
function createBasicShapeMesh( type, parameters ) {
  
  let mesh;

  switch( type ) {
    
    case "Box":

      var sx = parameters[0] &&  parameters[0] > 0 ? parameters[0] : 1;
      var sy = parameters[1] &&  parameters[1] > 0  ? parameters[1] : 1;
      var sz = parameters[2] &&  parameters[2] > 0  ? parameters[2] : 1;

      mesh = new THREE.Mesh( new THREE.BoxGeometry( sx, sy, sz ) );
      mesh.position.set( 0, sy / 2, 0 );

      break;
    case "Cylinder":

      var radiusTop = parameters[0] &&  parameters[0] > 0 ? parameters[0] : .5;
      var radiusBottom = parameters[1] &&  parameters[1] > 0  ? parameters[1] : .5;
      var height = parameters[2] &&  parameters[2] > 0  ? parameters[2] : 1;

      mesh = new THREE.Mesh( new THREE.CylinderGeometry( radiusTop, radiusBottom, height, 24 ) );
      mesh.position.set( 0, height / 2, 0 );

      break;
    case "Sphere":

      var radius = parameters[0] &&  parameters[0] > 0 ? parameters[0] : .5;

      mesh = new THREE.Mesh( new THREE.SphereGeometry( radius, 24, 24 ) );
      mesh.position.set( 0, radius, 0 );

      break;
    case "Cone":

      var radius = parameters[0] &&  parameters[0] > 0 ? parameters[0] : .5;
      var height = parameters[1] &&  parameters[1] > 0 ? parameters[1] : 1;

      mesh = new THREE.Mesh( new THREE.ConeGeometry( radius, height, 18 ) );
      mesh.position.set( 0, radius, 0 );

      break;
    case "Capsule":

      var radius = parameters[0] &&  parameters[0] > 0 ? parameters[0] : .5;
      var height = parameters[1] &&  parameters[1] > 0 ? parameters[1] : 1;

      mesh = new THREE.Mesh( new CapsuleGeometry( radius, height, 18 ) );
      mesh.position.set( 0, height * 0.5 + radius, 0 );

      break;

    case "Torus":

      var radius = parameters[0] && parameters[0] > 0 ? parameters[0] : 1;
      var tube = parameters[1] && parameters[1] > 0 ? parameters[1] : .4;

      const torusGeometry = new THREE.TorusGeometry( radius, tube, 18, 18 ) ;
      torusGeometry.rotateX( - Math.PI / 2 );
      mesh = new THREE.Mesh( torusGeometry );

      mesh.position.set( 0, tube, 0 );
      // mesh.quaternion.setFromAxisAngle( new THREE.Vector3( 1, 0, 0 ), -Math.PI / 2 );

      break;

    case "Plane":

      var width = parameters[0] && parameters[0] > 0 ? parameters[0] : 3;
      var height = parameters[1] && parameters[1] > 0 ? parameters[1] : 3;

      const planeGeometry = new THREE.PlaneGeometry( width, height, 4, 4 );
      planeGeometry.rotateX( - Math.PI / 2 );
      mesh = new THREE.Mesh( planeGeometry );
      // 物理模型默认高度(Z)值为0.002
      mesh.position.set( 0, 0.002, 0 );

      break;

    default:
      console.error( "不支持的形状类型:", type );
      break;
  }

  return mesh;

}

// 基础图形
class A3BasicShape extends A3Actor{
  
  name="basic_shape";

  constructor( type="Box", ...parameters ) {
    super();

    const mesh = createBasicShapeMesh( type, parameters );
    this.threeObject = mesh;
    this.physicsShape = getMeshShape( mesh, new THREE.Vector3( 1, 1, 1 ), true );
    // this.setFromMesh( mesh, 1.0 );
    this.setMaterial();
    this.type = type;
    
  }

}

// 物体产生器
class A3ObjectMaker extends A3Actor{

  isRandom = true;
  // 可视化
  boxSize = 1;
  boxColor = 0x1982cc;
  boxOpacity = 0.8;

  visible = true;

  // 物体参数
  objectMass = 1;
  // objectSize = 1;

  clock = new THREE.Clock();
  tCount = 0;
  speed = 1;  // 生产速度 单位秒

  constructor( position, size=1 ) {
    super();

    if( isNull( position ) ) {
      position = new THREE.Vector3( 0, 0, 0 );
    }

    const boxMatrial = new THREE.MeshPhongMaterial( { color: this.boxColor, transparent: true, opacity: this.boxOpacity } );
    this.threeObject = new THREE.Mesh( new THREE.BoxGeometry( size, size, size ), boxMatrial );

    this.threeObject.position.copy( position );
    this.position.copy( position );
    this.boxSize = size;
  }

  createObject( type="Box" ) {
    const newObject = new A3BasicShape( type, this.boxSize, this.boxSize, this.boxSize );
    // newObject.setPosition( this.position );
    newObject.recyclable = true;
    // newObject.setMass( this.objectMass );
    newObject.init( this.objectMass, this.position, this.quaternion );

    this.parent.addActor( newObject );
  }

  update() {
    this.tCount += this.clock.getDelta();

    if( this.tCount >= this.speed ) {
      this.createObject();
      this.tCount = 0;
    }
  }

}

// 物体回收器
class A3ObjectRecycler extends A3Actor {
  name='recycler';
  type='recycler';
  // 可视化
  boxSize = 1;
  boxColor = 0x19cc82;
  boxOpacity = 0.8;

  visible = true;

  constructor( position, size=1 ) {

    super();

    if( isNull( position ) ) {
      position = new THREE.Vector3( 0, 0, 0 );
    }

    const boxMatrial = new THREE.MeshPhongMaterial( { color: this.boxColor, transparent: true, opacity: this.boxOpacity } );
    this.threeObject = new THREE.Mesh( new THREE.BoxGeometry( size, size, size ), boxMatrial );

    this.threeObject.position.copy( position );
    this.position.copy( position );
    this.boxSize = size;

  }

  inRecyclerBox( position ) {

    var isInBox = true;
    if(Math.abs( position.x - this.position.x ) > this.boxSize / 2 ) {
      isInBox = false;
    }

    if(Math.abs( position.y - this.position.y ) > this.boxSize / 2 ) {
      isInBox = false;
    }

    if(Math.abs( position.z - this.position.z ) > this.boxSize / 2 ) {
      isInBox = false;
    }

    return isInBox;
  }

  update() {

    const actors = this.parent.actors;

    actors.forEach( actor=>{
      if( actor.recyclable && this.inRecyclerBox( actor.position ) ) {
        this.parent.removeActor( actor );
      }
    })

  }
}

export default A3BasicShape;

export { 
  BasicShapeTypes,
  A3ObjectMaker,
  A3ObjectRecycler,
};